package com.daffodil.core.dao.helper;

import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Field;
import java.sql.Blob;
import java.sql.Clob;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.Query;

import com.daffodil.core.entity.BaseEntity;
import com.daffodil.core.exception.BusinessException;
import com.daffodil.util.ReflectUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * Dao帮助类
 * 
 * @author yweijian
 * @date 2022年3月3日
 * @version 1.0
 * @description
 */
@Slf4j
public class DaoHelper {

	/**
	 * 将查询语句中的占位符[?]替换成[?i]<br>
	 * 如：from table where id = ? and name = ?<br>
	 * -> from table where id = ?0 and name = ?1
	 * 
	 * @param hql
	 * @return
	 */
	public static String getQueryHql(String hql) {
		return getQuerySql(hql);
	}
	
	/**
	 * 将查询语句中的占位符[?]替换成[?i]<br>
	 * 如：from table where id = ? and name = ?<br>
	 * -> from table where id = ?0 and name = ?1
	 * 
	 * @param sql
	 * @return
	 */
	public static String getQuerySql(String sql) {
		StringBuffer sb = new StringBuffer();
		Pattern pattern = Pattern.compile("[?]");
		Matcher matcher = pattern.matcher(sql);
		boolean result = matcher.find();
		int count = 0;
		while (result) {
			matcher.appendReplacement(sb, "?" + count);
			count++;
			result = matcher.find();
		}
		matcher.appendTail(sb);
		return sb.toString();
	}

	/**
	 * 设置query参数
	 * 
	 * @param query
	 * @param paras
	 * @throws BusinessException
	 */
	public static void setQueryParas(Query query, List<Object> paras) throws BusinessException {
		if ((paras != null) && (paras.size() > 0)) {
			for (int i = 0; i < paras.size(); i++) {
				query.setParameter(i, paras.get(i));
			}
		}
	}

	/**
	 * 获取count的sql
	 * 
	 * @param hql
	 * @return
	 */
	public static String getQueryCountHql(String hql) {
		if (hql.indexOf(" order ") > -1) {
			return "select count(*) " + hql.substring(hql.indexOf("from"), hql.indexOf("order"));
		}
		if (hql.indexOf(" group ") > -1) {
			return "select count(*) " + hql.substring(hql.indexOf("from"), hql.indexOf("group"));
		}
		return "select count(*) " + hql.substring(hql.indexOf("from"));
	}
	
	/**
	 * 获取count的sql
	 * 
	 * @param hql
	 * @return
	 */
	public static String getQueryCountSql(String sql) {
		if (sql.indexOf(" order ") > -1) {
			return "select count(*) as count " + sql.substring(sql.indexOf(" from "), sql.indexOf(" order "));
		}
		if (sql.indexOf(" group ") > -1) {
			return "select count(*) as count " + sql.substring(sql.indexOf(" from "), sql.indexOf(" group "));
		}
		return "select count(*) as count " + sql.substring(sql.indexOf(" from "));
	}

	/**
	 * 类对象合并
	 * 
	 * @param sourceBean
	 * @param targetBean
	 * @return
	 */
	public static BaseEntity<?> combineBean(BaseEntity<?> sourceBean, BaseEntity<?> targetBean) {
		Field[] sourceFields = sourceBean.getClass().getDeclaredFields();
		for (int i = 0; i < sourceFields.length; i++) {
			Field sourceField = sourceFields[i];
			if (!"serialVersionUID".equals(sourceField.getName())) {
				Object value = ReflectUtils.invokeGetter(sourceBean, sourceField.getName());
				if(null != value) {
					ReflectUtils.invokeSetter(targetBean, sourceField.getName(), value);
				}
			}
		}
		return targetBean;
	}

	/**
	 * 
	 * @param o
	 * @return
	 * @throws BusinessException
	 */
	public static String objectDataToString(Object o) throws BusinessException {
		if (o == null) {
			return "";
		}
		if (o instanceof Clob) {
			return clobToString((Clob) o);
		}
		if (o instanceof java.sql.Blob) {
			return blobToString((Blob) o);
		}
		return o.toString();
	}

	/**
	 * 把大对象CLOB转换成String
	 * 
	 * @param clob
	 * @return
	 */
	public static String clobToString(Clob clob) {

		if (clob == null) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		Reader clobStream = null;
		try {
			clobStream = clob.getCharacterStream();
			char[] c = new char[8112];// 每次获取8K
			int i = 0;
			while ((i = clobStream.read(c)) != -1) {
				sb.append(c, 0, i);
			}
			return sb.toString();
		} catch (Exception e) {
			throw new BusinessException("[JDBC] Clob数据转换错误 ...", e);
		} finally {
			try {
				if (clobStream != null) {
					clobStream.close();
				}
			} catch (Exception e) {
				log.warn(e.getMessage(), e);
			}
		}
	}

	/**
	 * 把大对象BLOB转换成String
	 * 
	 * @param blob
	 * @return
	 */
	public static String blobToString(Blob blob) {

		StringBuffer str = new StringBuffer();

		InputStream in = null;// 输入字节流
		try {
			in = blob.getBinaryStream();
			byte[] buff = new byte[(int) blob.length()];
			for (; (in.read(buff)) > 0;) {
				str = str.append(new String(buff));
			}
			return str.toString();
		} catch (Exception e) {
			throw new BusinessException("[JDBC] Blob数据转换错误 ...", e);
		} finally {
			try {
				if(in != null) {
					in.close();
				}
			} catch (Exception e) {
				log.warn(e.getMessage(), e);
			}
		}
	}
}
